home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
music
/
eked-m1.zoo
/
src
/
vk.c
< prev
Wrap
C/C++ Source or Header
|
1995-02-19
|
7KB
|
233 lines
/*
* EKED-M1 : Editor for Korg M1 synth; defs.h : virtual keyboard
* Copyright (C) 1995 Steven M. Eker (Steven.Eker@brunel.ac.uk)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stddef.h>
#include <string.h>
#include <gemfast.h>
#include <aesbind.h>
#include <vdibind.h>
#include "gm/gem_man.h"
#include "eked-m1.h"
#include "defs.h"
#include "types.h"
#include "externs.h"
#define WHITE_WIDTH 9
#define WHITE_LEN (5 * char_h - 2)
#define WHITE_M_TOP (4 * char_h - 2)
#define WHITE_M_BOT (5 * char_h - 3)
#define BLACK_WIDTH 5
#define BLACK_LEN (3 * char_h - 2)
#define BLACK_M_TOP (2 * char_h - 2)
#define BLACK_M_BOT (3 * char_h - 3)
#define OCT_WIDTH (7 * WHITE_WIDTH)
#define MIDI_LOW_C 36
#define MIDI_VEL1 64
#define MIDI_VEL2 127
#define MIDI_RVEL 64
typedef struct {
int left_edge;
int color;
} KEY_POS;
static KEY_POS key[] = {
{0, WHITE}, {6, BLACK}, {9, WHITE}, {17, BLACK}, {18, WHITE}, {27, WHITE},
{33, BLACK}, {36, WHITE}, {43, BLACK}, {45, WHITE}, {53, BLACK}, {54, WHITE}
};
static int vk_handle = -1;
static selected = -1;
static void display(int x_pos, int y_pos, GRECT *clip, long usr_val);
static int action(int handle, E_TYPE type, void *event,
int x_pos, int y_pos, long usr_val);
static int find_key(int x, int y);
static void update_marker(int handle, int x_pos, int y_pos, int note);
void vk_window()
{
if(vk_handle < 0){
vk_handle = wm_open(NAME | CLOSER | MOVER,
(GRECT *) 0, "Virtual Keyboard",
5 * OCT_WIDTH + 1, 5 * char_h, 0, 0,
&display, &action, 0L);
if(vk_handle < 0)
fm_alert(1, WINDOW_ALERT);
}
else
wm_topped(vk_handle);
}
static void display(int x_pos, int y_pos, GRECT *clip, long usr_val)
{
int point[4];
int i, j, e, x;
int black_len = BLACK_LEN, white_len = WHITE_LEN;
GM_AES2VDI(point, clip);
vs_clip(shared_handle, 1, point);
vsf_color(shared_handle, WHITE);
vr_recfl(shared_handle, point);
vsf_color(shared_handle, BLACK);
i = (point[0] - x_pos) / OCT_WIDTH;
e = (point[2] - x_pos) / OCT_WIDTH;
if(e == 5){ /* right most edge */
point[0] = point[2];
point[1] = y_pos + 1;
point[3] = y_pos + white_len;
vr_recfl(shared_handle, point);
e = 4;
}
for(x = x_pos + i * OCT_WIDTH; i <= e; i++, x += OCT_WIDTH){
for(j = 0; j < 12; j++){
point[1] = y_pos + 1;
point[0] = x + key[j].left_edge;
if(key[j].color == WHITE){
point[2] = point[0];
point[3] = y_pos + white_len;
if(j != 0 && j != 5)
point[1] += black_len;
}
else{
point[2] = point[0] + BLACK_WIDTH - 1;
point[3] = y_pos + black_len;
}
vr_recfl(shared_handle, point);
}
}
point[0] = x_pos;
point[2] = x_pos + 5 * OCT_WIDTH;
point[1] = point[3] = y_pos;
vr_recfl(shared_handle, point);
point[1] = point[3] = y_pos + white_len + 1;
vr_recfl(shared_handle, point);
if(selected >= 0){
i = selected % 12;
x = x_pos + OCT_WIDTH * (selected / 12);
if(key[i].color == WHITE){
point[0] = x + key[i].left_edge + 2;
point[2] = point[0] + WHITE_WIDTH - 4;
point[1] = y_pos + WHITE_M_TOP;
point[3] = y_pos + WHITE_M_BOT;
vr_recfl(shared_handle, point);
}
else{
point[0] = x + key[i].left_edge + 1;
point[2] = point[0] + BLACK_WIDTH - 3;
point[1] = y_pos + BLACK_M_TOP;
point[3] = y_pos + BLACK_M_BOT;
vsf_color(shared_handle, WHITE);
vr_recfl(shared_handle, point);
}
}
}
static int action(int handle, E_TYPE type, void *event,
int x_pos, int y_pos, long usr_val)
{
int new, old, m_x, m_y, m_state, k_state;
switch(type){
case E_CLEANUP:
vk_handle = -1;
break;
case E_CLICK:
wind_update(BEG_MCTRL);
do{
graf_mkstate(&m_x, &m_y, &m_state, &k_state);
new = m_state == 0 ? NIL : find_key(m_x - x_pos, m_y - y_pos);
old = selected;
if(new != old){
selected = new;
if(old != NIL){
tx_note_off(MIDI_LOW_C + old, MIDI_RVEL);
update_marker(handle, x_pos, y_pos, old);
}
if(new != NIL){
tx_note_on(MIDI_LOW_C + new, (k_state & 3) ? MIDI_VEL2 : MIDI_VEL1);
update_marker(handle, x_pos, y_pos, new);
}
}
}while(m_state != 0 || k_state != 0);
wind_update(END_MCTRL);
break;
}
return R_NORMAL;
}
static int find_key(int x, int y)
{
static white_map[] = {0, 2, 4, 5, 7, 9, 11};
int i, oct;
if(y <= 0 || y > WHITE_LEN || x <= 0 || x >= 5 * OCT_WIDTH)
return NIL;
oct = x / OCT_WIDTH;
x = x % OCT_WIDTH;
if(y > BLACK_LEN){
i = x / WHITE_WIDTH;
if(x % WHITE_WIDTH != 0)
return 12 * oct + white_map[i];
}
else{
for(i = 11; i >= 0; i--){
if(x >= key[i].left_edge){
if(key[i].color == WHITE){
if(i == 0 || i == 5){
if(x == key[i].left_edge) /* B->C or E->F edge */
break;
}
else{
if(key[i - 1].left_edge + BLACK_WIDTH - 1 >= x)
i--; /* black note actually covers part of D, E, G, A, B */
}
}
return 12 * oct + i;
}
}
}
return NIL;
}
static void update_marker(int handle, int x_pos, int y_pos, int note)
{
GRECT area;
area.g_x = x_pos + OCT_WIDTH * (note / 12);
note %= 12;
if(key[note].color == WHITE){
area.g_x += key[note].left_edge + 2;
area.g_w = WHITE_WIDTH - 3;
area.g_y = y_pos + WHITE_M_TOP;
area.g_h = WHITE_M_BOT - WHITE_M_TOP + 1;
}
else{
area.g_x += key[note].left_edge + 1;
area.g_w = BLACK_WIDTH - 2;
area.g_y = y_pos + BLACK_M_TOP;
area.g_h = BLACK_M_BOT - BLACK_M_TOP + 1;
}
wm_redraw(handle, &area);
}